package com.bodu.core.task;

import com.bodu.system.entity.vo.CronTriggersVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Slf4j
@Component
public class QuartzTaskBean {

    @Autowired
    private Scheduler scheduler;
    private static  final String SCHEDULER_GROUP_NAME = "default";
    /**
     * 创建定时任务 定时任务创建之后默认启动状态
     *
     * @return: void
     **/
    public void createScheduleJob( CronTriggersVo cron) throws SchedulerException, ClassNotFoundException {
        //获取到定时任务的执行类  必须是类的绝对路径名称
        //定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。
//        Class<? extends Job> jobClass = QuartzJobBean.class;
        String cronClass = cron.getCronTriggersClass();
        Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(cronClass);

        // 构建定时任务信息
        // "default" 默认组
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(cron.getId().toString(), SCHEDULER_GROUP_NAME).build();
        // 设置定时任务执行方式
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron.getCronExpression());
        // 构建触发器trigger
        // 如果已经有下一次时间，就设置为下一次时间为触发时间
        CronTrigger trigger;
        if (!Objects.isNull(cron.getNextTime())) {
            Date date = cron.getNextTime();
            trigger = TriggerBuilder.newTrigger().startAt(date)
                    .withIdentity(cron.getId().toString(), SCHEDULER_GROUP_NAME).withSchedule(scheduleBuilder).build();
        } else {
            trigger = TriggerBuilder.newTrigger().startNow()
                    .withIdentity(cron.getId().toString(), SCHEDULER_GROUP_NAME).withSchedule(scheduleBuilder).build();
        }
        scheduler.scheduleJob(jobDetail, trigger);
        // 设置下次执行时间
      /*  LocalDateTime nextTime = DateUtil.dateToLocalDate(trigger.getNextFireTime());
        log.info("下次一执行时间:{}",nextTime);
        reportSubscribe.setNextTime(nextTime);*/
    }

    /**
     * 根据任务名称暂停定时任务
     *
     * @param jobName   定时任务名称（这里直接用ReportSubscribePO的Id）
     * @throws SchedulerException
     */
    public void pauseScheduleJob( String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName, "default");
        scheduler.pauseJob(jobKey);
    }

    /**
     * 根据任务名称恢复定时任务
     *
     * @param cron   定时任务名称（这里直接用ReportSubscribePO的Id）
     * @throws SchedulerException
     */
    public void resumeScheduleJob( CronTriggersVo cron) throws SchedulerException, ClassNotFoundException {
        // 判断当前任务是否在调度中
        Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals("default"));
        List<JobKey> thisNameJobs = jobKeys.stream().filter(jobKey -> Objects.equals(cron.getId().toString(), jobKey.getName())).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(thisNameJobs)){
            JobKey jobKey = JobKey.jobKey(cron.getId().toString(),"default");
            scheduler.resumeJob(jobKey);
            // 下一次执行时间设置回去
            Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(cron.getId().toString(), "default"));
            cron.setNextTime(trigger.getNextFireTime());
        }else {
            createScheduleJob(cron);
        }
    }

    /**
     * 更新定时任务
     *
     * @param reportSubscribe 报告订阅对象
     * @throws SchedulerException
     */
    public void updateScheduleJob( CronTriggersVo reportSubscribe) throws SchedulerException {
        //获取到对应任务的触发器
        TriggerKey triggerKey = TriggerKey.triggerKey(reportSubscribe.getId().toString(),SCHEDULER_GROUP_NAME);
        //设置定时任务执行方式
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(reportSubscribe.getCronExpression());
        //重新构建任务的触发器trigger
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        if (trigger == null){
            return;
        }
        //  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
        trigger = TriggerBuilder.newTrigger().startNow()
                .withIdentity(reportSubscribe.getId().toString(), SCHEDULER_GROUP_NAME).withSchedule(scheduleBuilder).build();

        //重置对应的job
        scheduler.rescheduleJob(triggerKey, trigger);

        reportSubscribe.setNextTime(trigger.getNextFireTime());
    }

    /**
     * 根据定时任务名称从调度器当中删除定时任务
     *
     * @param jobName   定时任务名称 （这里直接用ReportSubscribePO的Id）
     * @throws SchedulerException
     */
    public void deleteScheduleJob(String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName,SCHEDULER_GROUP_NAME);
        scheduler.deleteJob(jobKey);
    }
}
